package com.budwk.app.util;

import com.alibaba.fastjson.JSONObject;
import com.budwk.app.common.config.AppException;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.xwpf.NiceXWPFDocument;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.xmlbeans.XmlException;
import org.nutz.mvc.upload.TempFile;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.springframework.core.io.ClassPathResource;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 7788
 * @version 12.0
 * @date 2021/1/6 下午 3:38
 * @location wuhan
 * 文档地址
 * http://deepoove.com/poi-tl/apache-poi-guide.html#_文档xwpfdocument
 * http://deepoove.com/poi-tl/#_%E7%A4%BA%E4%BE%8B
 */
@Slf4j
public class PoiTlUtil {

    public static void main(String[] args) throws Exception {
        HashMap a = new HashMap<>();
        a.put("A38","巡查基础事项：1、消防设施A10 齐全（）；较全（）；欠缺（）；无（）。2、店堂厨房用火（电）A12 安全（）；较安全（）；安全度低（）；不安全（）。3、店堂厨房用火（气）A11安全（）；较安全（）；安全度低（）；不安全（）。4、自查工作记录A13 齐全（）；较全（）；欠缺（）；无（）。5、技防设施A14 齐全（）；较全（）；欠缺（）；无（）。\n" +
                "巡查发现的问题：巡查基础事项：1、消防设施A10 齐全（）；较全（）；欠缺（）；无（）。2、店堂厨房用火（电）A12 安全（）；较安全（）；安全度低（）；不安全（）。3、店堂厨房用火（气）A11安全（）；较安全（）；安全度低（）；不安全（）。4、自查工作记录A13 齐全（）；较全（）；欠缺（）；无（）。5、技防设施A14 齐全（）；较全（）；欠缺（）；无（）。\\n\" +\n" +
                "                \"巡查发现的问题：巡查基础事项：1、消防设施A10 齐全（）；较全（）；欠缺（）；无（）。2、店堂厨房用火（电）A12 安全（）；较安全（）；安全度低（）；不安全（）。3、店堂厨房用火（气）A11安全（）；较安全（）；安全度低（）；不安全（）。4、自查工作记录A13 齐全（）；较全（）；欠缺（）；无（）。5、技防设施A14 齐全（）；较全（）；欠缺（）；无（）。\\n\" +\n" +
                "                \"巡查发现的问题：");
        word2RedDocument("C:\\Users\\XYD-PC021\\Desktop\\a.docx",a,"C:\\Users\\XYD-PC021\\Desktop\\", "tt.docx");
    }

    /**
     * @param content  公文源文件地址
     * @param data     需要填写的参数
     * @param destDocx 保存的文件地址
     * @param fileName 设置的文件名称
     */
    public static void word2RedDocument(String content, Map<String, Object> data, String destDocx, String fileName) throws Exception {
        File file = new File(destDocx);
        if (!file.exists()) {
            file.mkdirs();
        }
        //红头文件模板
        InputStream resourceAsStream = new FileInputStream("C:\\Users\\XYD-PC021\\Desktop\\a.docx");
        XWPFTemplate template = XWPFTemplate.compile(resourceAsStream).render(data);
        //获取模板
        NiceXWPFDocument main = template.getXWPFDocument();
        //签章
        XWPFParagraph paragraph = null;
        //XWPFRun targetRun = null;
        List<XWPFParagraph> xwpfParagraphList = main.getParagraphs();
        for (XWPFParagraph x : xwpfParagraphList) {
            String text = x.getText();
            if (text.contains("盖章")) {
                paragraph = x;
                break;
            }
        }
        if (paragraph != null) {
            //添加印章图片
            XWPFRun targetRun = paragraph.createRun();
            InputStream inputStream =
                    new FileInputStream("C:\\Users\\XYD-PC021\\Desktop\\z.png");
            targetRun.addPicture(inputStream, XWPFDocument.PICTURE_TYPE_JPEG, "sign", Units.toEMU(100), Units.toEMU(100));
            inputStream.close();
            log.info(fileName + " 盖章...");
            CTR targetRunCtr = targetRun.getCTR();
            if (targetRunCtr.sizeOfDrawingArray() > 0) {
                CTDrawing drawing = targetRunCtr.getDrawingArray(0);
                if (drawing.sizeOfInlineArray() > 0) {
                    CTGraphicalObject graphic = drawing.getInlineArray(0).getGraphic();
                    //log.info("graphic   " + graphic.toString());
                    //拿到新插入的图片替换添加CTAnchor 设置浮动属性 删除inline属性
                    CTAnchor anchor = getAnchorWithGraphic(graphic, "Seal" + System.currentTimeMillis(),
                            Units.toEMU(100), Units.toEMU(100),
                            Units.toEMU(160), Units.toEMU(-50), false);
                    //log.info("anchor   " + anchor.toString());
                    drawing.setAnchorArray(new CTAnchor[]{anchor});
                    drawing.removeInline(0);
                }
                //log.info("drawing   " + drawing.toString());
            }
        }
        //输出文件
        FileOutputStream out = new FileOutputStream(destDocx + fileName);
        main.write(out);
        main.close();
        out.close();

    }

    /**
     * @param ctGraphicalObject 图片数据
     * @param deskFileName      图片描述
     * @param width             宽
     * @param height            高
     * @param leftOffset        水平偏移 left
     * @param topOffset         垂直偏移 top
     * @param behind            文字上方，文字下方
     * @return
     * @throws Exception
     */
    public static CTAnchor getAnchorWithGraphic(CTGraphicalObject ctGraphicalObject,
                                                String deskFileName, int width, int height,
                                                int leftOffset, int topOffset, boolean behind) {
        String anchorXML =
                "<wp:anchor xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" "
                        + "simplePos=\"0\" relativeHeight=\"0\" behindDoc=\"" + ((behind) ? 1 : 0) + "\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\">"
                        + "<wp:simplePos x=\"0\" y=\"0\"/>"
                        + "<wp:positionH relativeFrom=\"column\">"
                        + "<wp:posOffset>" + leftOffset + "</wp:posOffset>"
                        + "</wp:positionH>"
                        + "<wp:positionV relativeFrom=\"paragraph\">"
                        + "<wp:posOffset>" + topOffset + "</wp:posOffset>" +
                        "</wp:positionV>"
                        + "<wp:extent cx=\"" + width + "\" cy=\"" + height + "\"/>"
                        + "<wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/>"
                        + "<wp:wrapNone/>"
                        + "<wp:docPr id=\"1\" name=\"Drawing 0\" descr=\"" + deskFileName + "\"/><wp:cNvGraphicFramePr/>"
                        + "</wp:anchor>";

        CTDrawing drawing = null;
        try {
            drawing = CTDrawing.Factory.parse(anchorXML);
        } catch (XmlException e) {
            e.printStackTrace();
        }
        CTAnchor anchor = drawing.getAnchorArray(0);
        anchor.setGraphic(ctGraphicalObject);
        return anchor;
    }

    /**
     * 获取导入数据的所有字段，并转为驼峰存储 如 user_id  -> userId
     * @param sheet
     * @return
     */
    public static List<String> getImportFields(Sheet sheet) {
        Row row = sheet.getRow(1);
        int cellIndex = 0;
        List<String> list = new ArrayList<>();
        while (true) {
            Cell cell = row.getCell(cellIndex);
            if (cell == null) {
                break;
            }
            String value = cell.getStringCellValue();
            if (StringUtils.isEmpty(value)) {
                break;
            }
            // 转为下划线驼峰
            String str = StrUtil.lineToHump(value);
            list.add(str);
            cellIndex ++;
        }
        return list;
    }

    public static Sheet getBookSheet(TempFile file) {
        try {
            IOUtils.setByteArrayMaxOverride(2000000000);
            Workbook book = WorkbookFactory.create(file.getInputStream()); //创建工作簿
            Sheet sheet = book.getSheetAt(0);//获取到工作表
            int lastRowNum = sheet.getLastRowNum();//获取到表格最后一行
            if (lastRowNum < 1 ) {
                throw new AppException("你未导入任何数据，请添加数据后导入...");
            }
            return sheet;
        } catch (IOException e) {
            log.error("poiUtil getBookSheet error: ", e);
            throw new AppException("获取单元格失败!");
        }
    }

    /**
     * 获取所有导入的数据json存储
     * @param sheet 单元格
     * @param startRow 数据起始行
     */
    public static List<JSONObject> getImportContent(Sheet sheet, int startRow) {
        List<JSONObject> results = new ArrayList<>();
        // 获取所有行的标题字段
        List<String> importFields = PoiTlUtil.getImportFields(sheet);
        // 获取表格数据
        for (int rowIndex = startRow; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
            JSONObject jsonObject = new JSONObject();
            Row row = sheet.getRow(rowIndex);
            for (int i = 0; i < importFields.size(); i++) {
                Cell cell = row.getCell(i);
                String value = new DataFormatter().formatCellValue(cell);
                jsonObject.put(importFields.get(i), value);
            }
            results.add(jsonObject);
        }
        return results;
    }
}

